<?php


namespace app\admin\controller;

use app\common\controller\AdminController;
use Fairy\HttpCrontab;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use think\App;

/**
 * 定时任务
 * Class SystemCrontab
 * @package app\admin\controller
 * @ControllerAnnotation(title="定时任务管理")
 */
class SystemCrontab extends AdminController
{
    private $baseUri;
    private $safeKey;

    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->baseUri = config('crontab.base_uri') ?: 'http://127.0.0.1:2345';
        $this->safeKey = config('crontab.safe_key') ?: null;
    }

    /**
     * @NodeAnotation(title="列表")
     */
    public function index()
    {
        if ($this->request->isAjax()) {
            $response = $this->httpRequest(HttpCrontab::INDEX_PATH . '?' . $this->request->query());
            if ($response['ok']) {
                $data = [
                    'code'  => 0,
                    'msg'   => '',
                    'count' => $response['data']['total'],
                    'data'  => $response['data']['data'],
                ];

            } else {
                $data = [
                    'code'  => 1,
                    'msg'   => $response['msg'],
                    'count' => 0,
                    'data'  => [],
                ];

            }

            return json($data);
        }
        return $this->fetch();
    }

    /**
     * @NodeAnotation(title="添加")
     */
    public function add()
    {
        if ($this->request->isAjax()) {
            $post = $this->request->post();
            $rule = [
                'title|标题'         => 'require',
                'rule|任务执行表达式'     => 'require',
                'target|任务调用目标字符串' => 'require',
            ];
            $this->validate($post, $rule);
            $response = $this->httpRequest(HttpCrontab::ADD_PATH, 'POST', $post);
            $response['ok'] ? $this->success('保存成功') : $this->error($response['msg']);
        }

        return $this->fetch();
    }

    /**
     * @NodeAnotation(title="属性修改")
     */
    public function modify()
    {
        $post = $this->request->post();
        $rule = [
            'id|ID'    => 'require',
            'field|字段' => 'require',
            'value|值'  => 'require',
        ];
        $this->validate($post, $rule);
        if (!in_array($post['field'], $this->allowModifyFields)) {
            $this->error('该字段不允许修改：' . $post['field']);
        }
        $response = $this->httpRequest(HttpCrontab::MODIFY_PATH, 'POST', $post);
        $response['ok'] ? $this->success('修改成功') : $this->error($response['msg']);
    }

    /**
     * @NodeAnotation(title="删除")
     */
    public function delete($id)
    {
        $response = $this->httpRequest(HttpCrontab::DELETE_PATH, 'POST', ['id' => is_array($id) ? join(',', $id) : $id]);
        $response['ok'] ? $this->success('删除成功') : $this->error($response['msg']);
    }

    /**
     * @NodeAnotation(title="日志")
     * @throws GuzzleException
     */
    public function flow()
    {
        $id = $this->request->get('id');
        if ($this->request->isAjax()) {
            $response = $this->httpRequest(HttpCrontab::FLOW_PATH . '?' . $this->request->query());
            if ($response['ok']) {
                $data = [
                    'code'  => 0,
                    'msg'   => 'OK',
                    'count' => $response['data']['total'],
                    'data'  => $response['data']['data'],
                ];
            } else {
                $data = [
                    'code'  => 1,
                    'msg'   => $response['msg'],
                    'count' => 0,
                    'data'  => [],
                ];
            }

            return json($data);
        }

        return $this->fetch('', ['crontab_id' => $id]);
    }

    /**
     * @NodeAnotation(title="重启")
     * @throws GuzzleException
     */
    public function reload($id)
    {
        $response = $this->httpRequest(HttpCrontab::RELOAD_PATH, 'POST', ['id' => $id]);
        $response['ok'] ? $this->success('重启成功') : $this->error($response['msg']);
    }

    /**
     * @NodeAnotation(title="ping")
     * @throws GuzzleException
     */
    public function ping()
    {
        $response = $this->httpRequest(HttpCrontab::PING_PATH);
        return json(['code' => $response['ok'] ? 1 : 0]);
    }

    /**
     * @param string $url
     * @param string $method
     * @param array $form
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    protected function httpRequest($url, $method = 'GET', array $form = [])
    {
        try {
            $client   = new Client([
                'base_uri' => $this->baseUri,
                'headers'  => [
                    'key' => $this->safeKey
                ]
            ]);
            $response = $client->request($method, $url, ['form_params' => $form]);
            $data     = [
                'ok'   => true,
                'data' => json_decode($response->getBody()->getContents(), true)['data'],
                'msg'  => 'success',
            ];
        } catch (RequestException $e) {
            if ($e->hasResponse()) {
                $msg = json_decode($e->getResponse()->getBody()->getContents(), true)['msg'];
            } else {
                $msg = $e->getMessage();
            }
            $data = [
                'ok'   => false,
                'data' => [],
                'msg'  => $msg
            ];
        }

        return $data;
    }
}
